home *** CD-ROM | disk | FTP | other *** search
/ SGI Hot Mix 17 / Hot Mix 17.iso / HM17_SGI / research / lib / xinteranimate.pro < prev    next >
Text File  |  1997-07-08  |  12KB  |  347 lines

  1. ; $Id: xinteranimate.pro,v 1.11 1997/01/15 03:11:50 ali Exp $
  2. ;
  3. ; Copyright (c) 1992-1997, Research Systems, Inc.  All rights reserved.
  4. ;    Unauthorized reproduction prohibited.
  5.  
  6. ;+
  7. ; NAME:
  8. ;        XINTERANIMATE
  9. ;
  10. ; PURPOSE:
  11. ;    Display an animated sequence of images using X-windows Pixmaps.
  12. ;    The speed and direction of the display can be adjusted using 
  13. ;    the widget interface.
  14. ;
  15. ; CATEGORY:
  16. ;    Image display, widgets.
  17. ;
  18. ; CALLING SEQUENCE:
  19. ;    To initialize:
  20. ;        XINTERANIMATE, SET = [Sizex, Sizey, Nframes]
  21. ;
  22. ;    To load a single image:
  23. ;        XINTERANIMATE, IMAGE = Image, FRAME = Frame_Index
  24. ;
  25. ;    To load a single image that is already displayed in an existing window:
  26. ;        XINTERANIMATE, FRAME = Frame_index, $
  27. ;            WINDOW = [Window_Number [, X0, Y0, Sx, Sy]]
  28. ;    (This technique is much faster than reading back from the window.)
  29. ;
  30. ;    To display the animation after all the images have been loaded:
  31. ;        XINTERANIMATE [, Rate] 
  32. ;
  33. ;    To close and deallocate the pixmap/buffer (which also takes place
  34. ;    automatically when the user presses the "Done With Animation"
  35. ;    button or closes the window with the window manager):
  36. ;        XINTERANIMATE, /CLOSE
  37. ;
  38. ; OPTIONAL INPUTS:
  39. ;    Rate:    A value between 0 and 100 that represents the speed of the 
  40. ;        animation as a percentage of the maximum display rate.
  41. ;        The fastest animation is with a value of 100 and the slowest
  42. ;        is with a value of 0.  The default animation rate is 100.  
  43. ;        The animation must be initialized using the SET
  44. ;        keyword before calling XINTERANIMATE with a rate value.
  45. ;
  46. ; KEYWORD PARAMETERS:
  47. ;    CLOSE:    Set this keyword to delete the offscreen pixwins and Widget, 
  48. ;        freeing storage.
  49. ;
  50. ;    CYCLE: If set, cycle.  Normally, frames are displayed going either
  51. ;        forward or backwards.  If CYCLE is set, reverse direction
  52. ;        after the last frame in either direction is displayed.
  53. ;        Provide this keyword with the SET keyword.
  54. ;
  55. ;    FRAME:    The frame number when loading frames.  This keyword only has
  56. ;        an effect when used in conjunction with the SET keyword.
  57. ;        FRAME must be set to a number in the range 0 to Nframes-1.
  58. ;
  59. ;    GROUP:    The widget ID of the widget that calls XINTERANIMATE.  When 
  60. ;        this ID is specified, the death of the caller results in the 
  61. ;        death of XINTERANIMATE.
  62. ;
  63. ;    IMAGE:    A single image to be loaded at the animation position given 
  64. ;        by FRAME.  The keyword parameter FRAME must also be specified.
  65. ;
  66. ;    KEEP_PIXMAPS: If TRUE, XINTERANIMATE doesn't destroy the animation
  67. ;        pixmaps when it is killed. Calling it again without
  68. ;        going through the SET and LOAD steps will cause the same
  69. ;        animation to play without the overhead of creating
  70. ;        the pixmaps.
  71. ;    ORDER:    Set this keyword to display images from the top down instead
  72. ;        of the default bottom up.  This keyword is only used when 
  73. ;        loading images.
  74. ;
  75. ;     SHOWLOAD:    Set this keyword (in conjunction with the SET keyword) to 
  76. ;        display each frame and update the frame slider as frames are 
  77. ;        loaded.
  78. ;
  79. ;    SET:    This keyword initializes XINTERANIMATE.  SET should be equated
  80. ;        to a 3-element integer vector containing the following 
  81. ;        parameters:
  82. ;          Sizex, Sizey:    The width and height of the images to be 
  83. ;                displayed, in pixels.
  84. ;
  85. ;          Nframes:    The number of frames in the animated sequence 
  86. ;                (since XINTERANIMATE is an animation routine, 
  87. ;                Nframes must be at least 2 frames).
  88. ;
  89. ;    TITLE:    A string to be used as the title of the widget.  If this 
  90. ;        keyword is not specified, the title is set to "XInterAnimate" 
  91. ;        This keyword has an effect only when used in conjunction with
  92. ;        the SET keyword).
  93. ;
  94. ;    TRACK: If set, the frame slider tracks the current frame.  Default
  95. ;        is not to track.  Provide this keyword with the SET keyword.
  96. ;
  97. ;    WINDOW:    When this keyword is specified, an image is copied from an 
  98. ;        existing window to the animation pixmap.  When using X 
  99. ;        windows, this technique is much faster than reading
  100. ;        from the display and then calling XINTERANIMATE with a 2D 
  101. ;        array.
  102. ;
  103. ;        The value of this parameter is either an IDL window
  104. ;        number (in which case the entire window is copied),
  105. ;        or a vector containing the window index and the rectangular 
  106. ;        bounds of the area to be copied, for example:
  107. ;        WINDOW = [Window_Number, X0, Y0, Sx, Sy]
  108. ;
  109. ;      XOFFSET:    The horizontal offset, in pixels from the left of the frame, 
  110. ;        of the image in the destination window.
  111. ;
  112. ;      YOFFSET:    The vertical offset, in pixels from the bottom of the frame,
  113. ;        of the image in the destination window.
  114. ;
  115. ; OUTPUTS:
  116. ;    No explicit outputs.
  117. ;
  118. ; COMMON BLOCKS:
  119. ;    XINTERANIMATE_COM: a private common block.
  120. ;
  121. ; SIDE EFFECTS:
  122. ;    A pixmap and widget are created.
  123. ;
  124. ; RESTRICTIONS:
  125. ;    Only a single copy of XINTERANIMATE can run at a time.
  126. ;
  127. ; PROCEDURE:
  128. ;    When initialized, this procedure creates an approximately square
  129. ;    pixmap or memory buffer, large enough to contain Nframes of
  130. ;    the requested size.  Once the images are loaded, using the 
  131. ;    IMAGE and FRAME keywords, they are displayed by copying the images 
  132. ;    from the pixmap or buffer to the visible draw widget.
  133. ;
  134. ; EXAMPLE:
  135. ;    Enter the following commands to open the file ABNORM.DAT (a series
  136. ;    of images of a human heart) and animate the images it contains using
  137. ;    XINTERANIMATE.  For a more detailed example of using XINTERANIMATE, 
  138. ;    see the example in the "Using IDL Widgets" chapter of "IDL Basics".
  139. ;    Read the images into the variable H by entering:
  140. ;
  141. ;        OPENR, 1, FILEPATH('abnorm.dat', SUBDIR = 'images')
  142. ;        H = BYTARR(64, 64, 16)
  143. ;        READU, 1, H
  144. ;        CLOSE, 1
  145. ;        H = REBIN(H, 128, 128, 16)
  146. ;
  147. ;    Initailize XINTERANIMATE with the command:
  148. ;
  149. ;        XINTERANIMATE, SET=[128, 128, 16], /SHOWLOAD
  150. ;        
  151. ;    Load the images into XINTERANIMATE and play the animation by entering:
  152. ;
  153. ;        FOR I=0,15 DO XINTERANIMATE, FRAME = I, IMAGE = H[*,*,I]
  154. ;        XINTERANIMATE
  155. ;
  156. ; MODIFICATION HISTORY:
  157. ;    DMS, April, 1990.
  158. ;    SMR, December, 1990.      Modified the XANIMATE code to work
  159. ;                interactively with widgets.
  160. ;
  161. ;    DMS, March, 1991.    Modified the routine to use individual pixmaps
  162. ;                for each frame of the animation.  Also added
  163. ;                the ability to read in from current IDL 
  164. ;                windows directly into offscreen bitmap.
  165. ;
  166. ;    SMR, March, 1991.    Modified to use new XMANAGER keyword CLEANUP
  167. ;                to clean up the offscreen pixmaps when dying.
  168. ;
  169. ;    SMR, Jan, 1992.        Modified the /CLOSE portion to check for a 
  170. ;                valid widget before using WIDGET_CONTROL 
  171. ;                and /DESTROY.
  172. ;
  173. ;    AB, June 1992        Rewrite using the new CW_ANIMATE compound
  174. ;                widget. Added the KEEP_PIXMAPS keyword.
  175. ;
  176. ;    DJE, April, 1996    Replaced XANNOUNCE with DIALOG_MESSAGE
  177. ;-
  178.  
  179. PRO xintanim_kill_pix
  180. ; If there are pixmaps currently open, free them.
  181.  
  182.   COMMON XInterAnimate_com, topbase, animatebase, pwin
  183.  
  184.   i = size(pwin)
  185.   if (i[0] ne 0) then begin        ; Not scalar, so contains valid IDs
  186.     i = i[i[0] + 2]            ; # of elements in pwin
  187.     FOR j=0, i-1 DO IF pwin[j] GE 0 THEN WDELETE, pwin[j] ;Delete the windows
  188.   pwin = -1        ;Show nothing there by setting to scalar value
  189.   endif
  190.  
  191. end
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200. PRO xintanim_event, ev
  201. ; The only event that can be seen by this application is the "DONE"
  202. ; event from the CW_ANIMATION cluster.
  203.  
  204.   widget_control, /destroy, ev.top
  205. END
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213. PRO XInterAnimate, RATE, SET = SET, IMAGE = IMAGE, FRAME = FRAME, $
  214.     ORDER = ORDER, CLOSE = CLOSE, TITLE = TITLE, $
  215.     SHOWLOAD = SHOWLOAD, GROUP = GROUP, WINDOW = WINDOW, $
  216.     XOFFSET = XOFFSET, YOFFSET = YOFFSET, KEEP_PIXMAPS=KEEP_PIXMAPS, $
  217.     CYCLE = cycle, TRACK = track
  218.  
  219. COMMON XInterAnimate_com, topbase, animatebase, pwin
  220.  
  221.  
  222. ;--------------------- CLOSE Portion of Xinteranimate -------------------------
  223.  
  224.   IF KEYWORD_SET(CLOSE) THEN BEGIN
  225.     if (widget_info(topbase, /valid)) THEN $
  226.       WIDGET_CONTROL, topbase, /DESTROY
  227.     xintanim_kill_pix
  228.     RETURN
  229.   ENDIF
  230.  
  231.   ;Don't allow two copies of xinternimate to run at once
  232.   IF xregistered("XInterAnimate") THEN begin
  233.     tmp = dialog_message( /error, [ 'Error in XINTERANIMATE:', ' ', $
  234.                   'Only one animation at a time is allowed.' ])
  235.     return
  236.   endif
  237.  
  238.  
  239.  
  240. ;----------------------  SET Portion of Xinteranimate ------------------------
  241.  
  242.   IF KEYWORD_SET(SET) THEN BEGIN
  243.  
  244.     swin = !d.window
  245.  
  246.     ;This is the first call to xinteranimate.  Here the pixmap is
  247.     ;    created and the widgets are initialized.
  248.  
  249.     xintanim_kill_pix                ;If old pixmap exists, delete 
  250.  
  251.     IF NOT(KEYWORD_SET(TITLE)) THEN TITLE = "XInterAnimate"
  252.     topbase = WIDGET_BASE(TITLE = TITLE)
  253.  
  254.     ; Setting the managed attribute indicates our intention to put this app
  255.     ; under the control of XMANAGER, and prevents our draw widgets from
  256.     ; becoming candidates for becoming the default window on WSET, -1. XMANAGER
  257.     ; sets this, but doing it here prevents our own WSETs at startup from
  258.     ; having that problem. Don't do this if SHOWLOAD is to be used because
  259.     ; we want it to grab the window then.
  260.     IF not KEYWORD_SET(SHOWLOAD) THEN WIDGET_CONTROL, /MANAGED, topbase
  261.  
  262.     animatebase = CW_ANIMATE(topbase, set[0], set[1], set[2], $
  263.         TRACK = KEYWORD_SET(track), CYCLE=KEYWORD_SET(cycle))
  264.  
  265.     ; If the SHOWLOAD keyword is set, realize things now so the load is seen
  266.     IF KEYWORD_SET(SHOWLOAD) THEN $
  267.       WIDGET_CONTROL, topbase, /REALIZE, /HOURGLASS
  268.  
  269.     WSET, swin
  270.     RETURN
  271.   ENDIF
  272.  
  273. ;-----------------  IMAGE Loading Portion of Xinteranimate --------------------
  274.  
  275.   nwindow = N_ELEMENTS(WINDOW)
  276.   nimage = N_ELEMENTS(image)
  277.   if (nwindow gt 0) or (nimage gt 0) then begin
  278.     old_window = !D.WINDOW                ;Save old window
  279.  
  280.     ; Make sure a widget has been created before trying to load it.
  281.     if (not widget_info(topbase, /valid)) then MESSAGE, 'Not initialized'
  282.  
  283.     IF (N_ELEMENTS(YOFFSET) EQ 0) THEN YOFFSET = 0
  284.     IF (N_ELEMENTS(XOFFSET) EQ 0) THEN XOFFSET = 0
  285.  
  286.     if (N_ELEMENTS(WINDOW) gt 0) then begin
  287.       CW_ANIMATE_LOAD, animatebase, frame=frame, window=window, $
  288.         XOFFSET = XOFFSET, YOFFSET = YOFFSET
  289.     endif else begin
  290.       IF (N_ELEMENTS(ORDER) EQ 0) THEN ORDER = 0
  291.       CW_ANIMATE_LOAD, animatebase, frame=frame, image=image, $
  292.         XOFFSET = XOFFSET, YOFFSET = YOFFSET, ORDER = ORDER
  293.     endelse
  294.     WSET, old_window
  295.     RETURN
  296.   ENDIF
  297.  
  298. ;---------------  Register and Run Portion of Xinteranimate -------------------
  299.  
  300.   ; If the base is not valid, it means that we have skipped
  301.   ; calling this routine with the SET keyword. In this case, we can restart
  302.   ; the last animation if the KEEP_PIXMAP keyword was used to preserve them
  303.   ; in the previous call.
  304.  
  305.   if (not widget_info(topbase, /valid)) then begin
  306.     s = size(pwin)
  307.     if (s[0] eq 0) then message, 'No image frames loaded'
  308.     ; Scan the pixmaps to figure out the image size
  309.     n = s[s[0] + 2]
  310.     xs = 0
  311.     for i = 0, n-1 do begin
  312.       if pwin[i] ne -1 then begin
  313.         old_window = !D.WINDOW
  314.     wset, pwin[i]
  315.         xs = !d.x_vsize
  316.         ys = !d.y_vsize
  317.     WSET, old_window
  318.         goto, found        ; Like a "break" in C
  319.       endif
  320.     endfor
  321.   found:
  322.     if (xs ne 0) then begin
  323.       IF NOT(KEYWORD_SET(TITLE)) THEN TITLE = 'XInterAnimate'
  324.       topbase = WIDGET_BASE(TITLE = TITLE)
  325.       animatebase = CW_ANIMATE(topbase, xs, ys, n, PIXMAPS=pwin)
  326.       ; The pixmaps are no longer our responsibility. They will get destroyed
  327.       ; by CW_ANIMATE as usual unless this invocation of XINTERANIMATE
  328.       ; specifies the KEEP_PIXMAP keyword. 
  329.       pwin = 0            ; Indicate that we aren't saving them anymore.
  330.     endif else message, 'No image frames loaded'
  331.   endif
  332.  
  333.  
  334.   ; At this point, the application must be realized if it isn't already
  335.   if (not widget_info(topbase, /realized)) then $
  336.     WIDGET_CONTROL, topbase, /REALIZE
  337.  
  338.   ; Save the pixmaps for later restart
  339.   if keyword_set(keep_pixmaps) then CW_ANIMATE_GETP, animatebase, pwin
  340.  
  341.   if N_ELEMENTS(RATE) EQ 0 THEN RATE = 100
  342.   cw_animate_run, animatebase, rate
  343.  
  344.   Xmanager, "XInterAnimate", topbase, EVENT_HANDLER = "xintanim_event", $
  345.       GROUP_LEADER = GROUP, /NO_BLOCK
  346. END
  347.